#pragma once

#define _MY_DEBUG
#ifdef _MY_DEBUG
#pragma warning(disable:4996) 
#pragma warning(disable:4127) 
class bitmap_image;
#define LOGT(arg) do { printf("%.2f ", m_game->match->timePassed); printf arg; } while (0)
#define LOG(arg) do { printf arg; } while (0)
#else
#define LOGT(arg) 
#define LOG(arg) 
#endif
#include <string>
#include <cstdlib>
#include <boost/none.hpp>
#include <boost/thread.hpp>

#include "api/GameInfo.h"
#include "api/Commands.h"
#include "api/Commander.h"
#include "api/CommanderFactory.h"

#define PI 3.141592f

#include "PathFinder.h"
#include "Action.h"

using namespace std;

namespace EGoal
{
    enum Type
    {
        None = 0,
        Attack,
        Defend,
        ReturnFlag,
    };
}

class MyBotInfo
{
public:
    MyBotInfo();
    ~MyBotInfo();
    void Clear();

    void Set(EGoal::Type goal, Action* a);
    void SetAction(Action* a);
    void SetGoal(EGoal::Type goal);

    Action* GetAction() const { return m_Action; }
    EGoal::Type GetGoal() const { return m_Goal; }


private:
    Action* m_Action;
    EGoal::Type m_Goal;
};



class MyCommander : public Commander
{
public:
    virtual string getName() const;
    virtual void initialize();
    virtual void tick();
    virtual void shutdown();

    const GameInfo& GetGame() const { return *m_game; }
    const LevelInfo& GetLevel() const { return *m_level; }
    const BotInfo& GetBot(const string& bot_name) const { return *m_game->bots[bot_name]; }
    PathFinder* GetPathFinder() const { return m_PathFinder; }

private:
    void ReassignBotRoles();

    uint GetOptimalNumDefenders();

    void UpdateFacts();
    void UpdateDefenders();
    void UpdateAssaults();
    void UpdateRunners();

    //
    bool HandleMatchEvents();
    void SetFlagPossessions();

    uint FindClosestBot(vector<BotInfo*> bots, const Vector2& pos);

    // debug
    void DumpCreate();
    void DumpDestroy(string name);
    void DumpImage();
    void DumpPath(const Path& path, uchar r, uchar g, uchar b);
    void DumpBuffer(const MapBuffer& buffer, const string& file_name, float v1, float v2); // v1 > v2
    void DumpBufferGradient(const MapBuffer& buffer, const string& file_name);

    bool SeeDanger(BotInfo* bot);

    void CalcAmbushPoint(MapBuffer& buffer, Vector2 src, Vector2 dest, vector<Vector2> ambush_points);
    void SelectFOV(MapBuffer& buffer, Vector2 p, Vector2 dir, float angle, float length, float selection_value);

    void CalcVisibilityMap(MapBuffer& buffer);
    Action* SelectNewAction(string bot_name);
    void CreateActions();

    bool m_MyPossession;
    bool m_EnemyPossession;
    bool m_SituationChanged;

    uint m_EnemyBotsAlive;

    float m_DefendersRatio;

    map<string, MyBotInfo*> m_MyBotInfo;

    Action* GetAction(const string& bot_name) { return m_MyBotInfo[bot_name]->GetAction(); }
    void SetAction(const string& bot_name, Action* new_action) { delete m_MyBotInfo[bot_name]->GetAction(); m_MyBotInfo[bot_name]->SetAction(new_action); }


    float m_DeltaTime;
    float m_LastTime;

    PathFinder* m_PathFinder;

    map<string, bool> m_botAliveState;

    vector<string> m_VisibleEnemies;

    float* m_MapData;
    MapBuffer* m_EnemyFieldOfFire;


#ifdef _MY_DEBUG
    bitmap_image* m_DebugImage;
#endif // _MY_DEBUG
};

REGISTER_COMMANDER(MyCommander);
